#基础特征计算类
import time

import pandas as pd

from Utils.DataLoaderAndSaver import DataLoaderAndSaver
from Utils.calFeatures import calLargerThanMas, closeUpPenetrateMas, calSTDS, calLessThanDays, calQuantile, calIncrease, \
    getMaOrder, maIncreaseDays, closeIncreaseDays, masUpPenetrate, volRatio, volIncreaseDays, decreaseFromMaxRecent, \
    increaseFromMinRecent, calMas, calAmplitude, calMinMaxRatio, isRecentDaysMin, isRecentDaysMax, recentDaysMax, \
    recentDaysMin, getCloseDF, calAroundMA, calSunDays, calSunDaysRatio, calRecentSunDays, calRecentNegativeDays, \
    closeDecreaseDays, calRecentNegativeDaysDecrease, calRecentSunDaysIncrease, closeUpPenetrateMa250, calHANegDays, \
    calHASunDays, volSumRatio, HAInvert, closeInvert


class ETFFeatureCalculation:
    def __init__(self,daysBefore1=0,daysBefore2=1,yearsBefore=4):
        # 基本的配置信信息,以及加载数据
        # self.increaseTable = 'table_basic_features'
        self.dataLoaderAndSaver = DataLoaderAndSaver(
            daysBefore1=daysBefore1,
            daysBefore2=daysBefore2,
            yearsBefore=yearsBefore,
            reload=False)
        self.codes = set(list(self.dataLoaderAndSaver.alletfs.index))
        self.dailyprices = self.dataLoaderAndSaver.loadETFDailyPrices()
        self.dailyprices.index=self.dailyprices['date']

    def calFeatures(self):
        maDays=[5,10,20,30,40,50,60,70,80,90,100,120,122,150,180,200,244,250]
        quantileDays=[30,40,50,60,90,100,122,244,366,488,610,732]
        increaseDays = [3, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 122, 150, 180, 200, 244, 250, 300, 366]
        recentDays=[10,20,30, 40, 50, 60, 70, 80, 90, 100, 120, 122, 150, 180, 200, 244, 250, 300, 366]
        count=0
        errorcode=[]
        start=time.time()
        for code in self.codes:
            try:
                print(code)
                dailyprices=self.dailyprices[self.dailyprices['code'] == code]
                if len(dailyprices)==0:
                    continue
                closeDF=getCloseDF(dailyprices,code)
                largerThanMasDF=calLargerThanMas(dailyprices,code,maDays,'larger_')
                closeUpPenetrateMasDF=closeUpPenetrateMas(dailyprices,code,maDays,'uppenetrate_')
                masDF=calMas(dailyprices,code,maDays,'ma_')
                closestdDF = calSTDS(dailyprices, code, maDays, 'close', 'closestd_')
                volstdDF=calSTDS(dailyprices,code,maDays,'volume','volstd_')
                moneystdDF = calSTDS(dailyprices, code, maDays, 'money', 'moneystd_')
                lessThanDF=calLessThanDays(dailyprices,code,[120,250],'lessthan_')
                quantileDF=calQuantile(dailyprices,code,quantileDays,'quant_')
                increaseDF=calIncrease(dailyprices,code,increaseDays,'increase_')
                # ismaOrderDF=getMaOrder(dailyprices,code,[5,10,20,30],'isma_v1')
                increaseMaDF=maIncreaseDays(dailyprices,code,maDays,'ma_increa_')
                closeIncreaseDF=closeIncreaseDays(dailyprices,code,'close_increa_')
                closeDecreaseDF=closeDecreaseDays(dailyprices,code,'close_decrea_')
                masUpPenetrateDF1=masUpPenetrate(dailyprices,code,5,30,'ma_')
                masUpPenetrateDF2 = masUpPenetrate(dailyprices, code, 5, 60, 'ma_')
                masUpPenetrateDF3 = masUpPenetrate(dailyprices, code, 5, 90, 'ma_')
                masUpPenetrateDF4 = masUpPenetrate(dailyprices, code, 5, 120, 'ma_')
                masUpPenetrateDF5 = masUpPenetrate(dailyprices, code, 30, 60, 'ma_')
                masUpPenetrateDF6 = masUpPenetrate(dailyprices, code, 30, 90, 'ma_')
                masUpPenetrateDF7 = masUpPenetrate(dailyprices, code, 30, 120, 'ma_')
                masUpPenetrateDF8 = masUpPenetrate(dailyprices, code, 90, 120, 'ma_')
                masUpPenetrateDF9 = masUpPenetrate(dailyprices, code, 90, 250, 'ma_')
                masUpPenetrateDF10 = masUpPenetrate(dailyprices, code, 120, 250, 'ma_')
                volratioDF=volRatio(dailyprices,code,'volratio')
                volSumRatioDF=volSumRatio(dailyprices,code,'volratio_5')
                volIncreaseDF=volIncreaseDays(dailyprices,code,'volincreasedays')
                decreaseFromMaxRecentDF=decreaseFromMaxRecent(dailyprices,code,recentDays,'decrease_from_max_')
                increaseFromMinRecentDF=increaseFromMinRecent(dailyprices,code,recentDays,'increase_from_min_')
                ampDF=calAmplitude(dailyprices, code, maDays,'amplitude_')
                minmaxRatioDF=calMinMaxRatio(dailyprices, code, maDays,'minmax_ratio_')
                isRecentDaysMinDF=isRecentDaysMin(dailyprices, code, maDays,'recent_min_')
                isRecentDaysMaxDF = isRecentDaysMax(dailyprices, code, maDays, 'recent_max_')
                recentDaysMinDF=recentDaysMin(dailyprices, code, maDays, 'recent_minclose_')
                recentDaysMaxDF = recentDaysMax(dailyprices, code, maDays, 'recent_maxclose_')
                aroundMADF=calAroundMA(dailyprices,code,488,'around_250')
                sundaysDF = calSunDays(dailyprices, code, recentDays, 'sundays_')
                sundaysRatioDF = calSunDaysRatio(dailyprices, code, recentDays, 'sundays_ratio_')
                recentSunDaysDF = calRecentSunDays(dailyprices, code, 'recent_sundays')
                recentSunDaysIncDF=calRecentSunDaysIncrease(dailyprices, code, 'recent_sundays_')
                negDaysDF = calRecentNegativeDays(dailyprices, code, 'recent_neg_days')
                negDaysDecDF=calRecentNegativeDaysDecrease(dailyprices, code, 'recent_neg_days_')
                closeUpPenetrateMa250DF = closeUpPenetrateMa250(dailyprices, code, 'uppenetrate_250_increase')
                haNegDaysDF=calHANegDays(dailyprices,code,'ha_negdays')
                haSunDaysDF=calHASunDays(dailyprices,code,'ha_sundays')
                haInvertDF = HAInvert(dailyprices, code, 'ha_invert_days')
                closeInvertDF = closeInvert(dailyprices, code, 'close_invert')
                # print(lessThanDF)
                # print(quantileDF)
                finalDF=pd.concat([
                    closeDF,
                    largerThanMasDF,closeUpPenetrateMasDF,masDF,
                    closestdDF,
                    volstdDF,moneystdDF,
                    lessThanDF,quantileDF,increaseDF,increaseMaDF,
                    closeIncreaseDF,closeDecreaseDF,
                    masUpPenetrateDF1,masUpPenetrateDF2,masUpPenetrateDF3,masUpPenetrateDF4,masUpPenetrateDF5,masUpPenetrateDF6,masUpPenetrateDF7,
                    masUpPenetrateDF8,masUpPenetrateDF9,masUpPenetrateDF10,
                    volratioDF,volSumRatioDF,volIncreaseDF,
                    decreaseFromMaxRecentDF,increaseFromMinRecentDF,
                    ampDF,
                    minmaxRatioDF,
                    isRecentDaysMinDF,isRecentDaysMaxDF,
                    recentDaysMinDF,recentDaysMaxDF,
                    aroundMADF,
                    sundaysDF, sundaysRatioDF, recentSunDaysDF,recentSunDaysIncDF,
                    negDaysDF,
                    negDaysDecDF,
                    closeUpPenetrateMa250DF,
                    haSunDaysDF,haNegDaysDF,
                    haInvertDF, closeInvertDF
                   ],axis=1)
                code=list(finalDF.index)[0]
                finalDF.insert(0,'code',code)
                finalDF.insert(0, 'date', self.dataLoaderAndSaver.todayDate)
                # finalDF.insert(0,'date',self.dataLoaderAndSaver.todayDate)
            # print(largerThanMasDF,closeUpPenetrateMasDF,volstdDF,moneystdDF,lessThanDF,
            #       quantileDF,increaseDF,ismaOrderDF,increaseMaDF,closeIncreaseDF,
            #       masUpPenetrateDF,
            #       volratioDF, volIncreaseDF, decreaseFromMaxRecentDF, increaseFromMinRecentDF
            #       )
                print(finalDF,finalDF.shape)
                print(','.join(finalDF.columns))
                tableName=('etfdaily_features_'+self.dataLoaderAndSaver.todayDate+'_v4').replace('-','_')
                # print(tableName)
                self.dataLoaderAndSaver.saveData(tableName,finalDF)
            except:
                print(code,'有误')
                errorcode.append(code)
            count = count + 1
            print(count,'of',len(self.codes))
        end=time.time()
        timeconsumption=end-start
        print('花费时间:%.2f秒,%.2f分钟,%.2f小时'%(timeconsumption,timeconsumption/60,timeconsumption/3600))
        print(errorcode)

etffc=ETFFeatureCalculation(-4,-3)
etffc.calFeatures()
